package android.game.BoxedIn;
import android.content.Context;
import android.util.AttributeSet;
import android.view.*;
import android.widget.Button;
import android.graphics.*;
import android.graphics.drawable.*;
import android.graphics.drawable.shapes.*;
import android.util.Log;

/*
 * GameBoardView class
 * Constructs the Android view responsible for drawing the gameboard, scores and managing game function.
 */
public class GameBoardView extends View {
	/*
	 * Constructor taking a context.
	 */
	public GameBoardView(Context context) {
		super(context);
		initResources();
	}

	/*
	 * Constructor taking a context and attribute set.
	 */
	public GameBoardView(Button okButton, Context context, AttributeSet attrs) {
		super(context, attrs);
		initResources();
	}

	/*
	 * Constructor taking a context, attribute set and style.
	 */
	public GameBoardView(Button okButton, Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		initResources();
	}
	
	/*
	 * Colour constants.
	 */
	private static final int BorderColour = 0xffffffff;
	private static final int BackgroundColour = 0xff000000;
	private static final int GridColour = 0xffaaaaaa;
	private static final int FenceColour = 0xff666666;
	private static final int SelectionColour = 0xffcccccc;
	
	private static final int[] PlayerColours = {
		0xffff0000, // Red.
		0xffffff00 // Yellow.
		};
	
	/*
	 * Shapes used for drawing the game board.
	 */
	private ShapeDrawable BackgroundBorder;
	private ShapeDrawable Background;
	private final ShapeDrawable[] Grid = new ShapeDrawable[64];
	private final ShapeDrawable[] Horiz = new ShapeDrawable[72];
	private final ShapeDrawable[] Verts = new ShapeDrawable[72];
	private ShapeDrawable Selection;
	private ShapeDrawable OkButtonBorder;
	private ShapeDrawable OkButton;
	
	/*
	 * Whether a fence is selected.
	 */
	private boolean DrawSelection = false; 
	private int Selected = -1;
	private boolean SelectedVertical = false;
	
	private int CurrentPlayer = GameRecord.PlayerOne;
	
	/*
	 * GameRecord contains tracks the game state.
	 */
	private final GameRecord Game = new GameRecord();
	
	/*
	 * Initialise the resources.
	 */
	private void initResources() {
		BackgroundBorder = new ShapeDrawable(new RectShape());
		BackgroundBorder.getPaint().setColor(BorderColour);
		BackgroundBorder.setBounds(5, 5, 315, 315);
		
		Background = new ShapeDrawable(new RectShape());
		Background.getPaint().setColor(BackgroundColour);
		Background.setBounds(10, 10, 310, 310);
		
		for(int c = 0; c < 64; ++c) {
			int x = 15 + ((c % 8) * 37);
			int y = 15 + ((c / 8) * 37);
			
			Grid[c] = new ShapeDrawable(new RectShape());
			Grid[c].getPaint().setColor(GridColour);
			Grid[c].setBounds(x, y, x + 32, y + 32);
		}
		
		for(int c = 0; c < 72; ++c) {
			int x = 15 + ((c % 8) * 37);
			int y = 10 + ((c / 8) * 37);
			Horiz[c] = new ShapeDrawable(new RectShape());
			Horiz[c].getPaint().setColor(FenceColour);
			Horiz[c].setBounds(x, y, x + 32, y + 5);
		}
		
		for(int c = 0; c < 63; ++c) {
			int x = 10 + ((c % 9) * 37);
			int y = 10 + ((c / 9) * 37);
			Verts[c] = new ShapeDrawable(new RectShape());
			Verts[c].getPaint().setColor(FenceColour);
			Verts[c].setBounds(x, y, x + 5, y + 37);
		}
		
		for(int c = 63; c < 72; ++c) {
			int x = 10 + ((c % 9) * 37);
			int y = 10 + ((c / 9) * 37);
			Verts[c] = new ShapeDrawable(new RectShape());
			Verts[c].getPaint().setColor(FenceColour);
			Verts[c].setBounds(x, y, x + 5, y + 42);
		}
		
		Selection = new ShapeDrawable(new RectShape());
		Selection.getPaint().setColor(SelectionColour);
		Selection.setBounds(Grid[0].getBounds());
		
		OkButtonBorder = new ShapeDrawable(new RectShape());
		OkButtonBorder.getPaint().setColor(BorderColour);
		OkButtonBorder.setBounds(250, 320, 320, 430);
		
		OkButton = new ShapeDrawable(new RectShape());
		OkButton.getPaint().setColor(GridColour);
		OkButton.setBounds(255, 325, 315, 425);
		
		/*takeTurn(4, 4, GameRecord.Top, GameRecord.PlayerOne);
		takeTurn(4, 4, GameRecord.Bottom, GameRecord.PlayerTwo);
		takeTurn(5, 4, GameRecord.Right, GameRecord.PlayerOne);
		takeTurn(5, 4, GameRecord.Top, GameRecord.PlayerTwo);
		takeTurn(4, 4, GameRecord.Left, GameRecord.PlayerOne);
		takeTurn(5, 4, GameRecord.Bottom, GameRecord.PlayerTwo);
		takeTurn(4, 4, GameRecord.Right, GameRecord.PlayerTwo); */
	}
	
	/*
	 * Reset the resources. 
	 */
	private void resetResources() {
		for(int c = 0; c < 64; ++c) {
			Grid[c].getPaint().setColor(GridColour);
			Horiz[c].getPaint().setColor(FenceColour);
			Verts[c].getPaint().setColor(FenceColour);
		}
		
		for(int c = 64; c < 72; ++c) {
			Horiz[c].getPaint().setColor(FenceColour);
			Verts[c].getPaint().setColor(FenceColour);
		}
	}
	
	/*
	 * Draws the game board.
	 */
	protected void onDraw(Canvas canvas) {
		BackgroundBorder.draw(canvas);
		Background.draw(canvas);
		
		for(int c = 0; c < 64; ++c) {
			Grid[c].draw(canvas);
			Horiz[c].draw(canvas);
			Verts[c].draw(canvas);
		}
		
		for(int c = 64; c < 72; ++c) {
			Horiz[c].draw(canvas);
			Verts[c].draw(canvas);
		}
		
		if(DrawSelection) {
			Selection.draw(canvas);
			OkButtonBorder.draw(canvas);
			OkButton.draw(canvas);
		}
	}
	
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
		
		Log.i("BoxedIn", "onMeasure called with: " + MeasureSpec.getSize(widthMeasureSpec) + ", " + MeasureSpec.getSize(heightMeasureSpec));
	}
	
	/*
	 * Take a turn.
	 */
	private void takeTurn(int which, boolean vertical, int player) {
		if(!Game.takeTurn(which, vertical, player)) {
			return;
		}
		
		if(vertical) {
			Verts[which].getPaint().setColor(PlayerColours[player]);
			
		} else {
			Horiz[which].getPaint().setColor(PlayerColours[player]);
		}
		
		int location = vertical ? ((which / 9) * 8) + (which % 9) : which;
		int location2 = vertical ? (((which / 9) * 8) + (which % 9)) - 1 : which - 8;
		
		if(location >= 0 && location <= 63) {
			if(Game.getFences(location) == 4) {
				Grid[location].getPaint().setColor(PlayerColours[player]);
			}
		}
		if(location2 >= 0 && location2 <= 63) {
			if(Game.getFences(location2) == 4) {
				Grid[location2].getPaint().setColor(PlayerColours[player]);
			}
		}
		
		invalidate();
	}
	
	
	
	/*
	 * Manages a touch event.
	 */
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		if(event.getAction() == MotionEvent.ACTION_DOWN) {
			int tx = (int)event.getX();
			int ty = (int)event.getY();
			
			boolean vertical = false;
			int which = -1;
			
			for(int c = 0; c < 72; ++c) {
				int x = 10 + ((c % 8) * 37);
				int y = 5 + ((c / 8) * 37);
				if(tx > x && tx < x + 32 && ty > y && ty < y + 15) {
					which = c;
					break;
				}
			}
			
			if(which == -1) {
				for(int c = 0; c < 72; ++c) {
					int x = 5 + ((c % 9) * 37);
					int y = 10 + ((c / 9) * 37);
					
					if(tx > x && tx < x + 15 && ty > y && ty < y + 32) {
						which = c;
						vertical = true;
						break;
					}
				}
			}
			
			if(which > -1 && Game.validTurn(which, vertical)) {
				if(vertical) {
					Selection.setBounds(Verts[which].getBounds());
				} else {
					Selection.setBounds(Horiz[which].getBounds());
				}
				
				Selected = which;
				SelectedVertical = vertical;
				
				DrawSelection = true;
			} else {
				Rect rect = OkButtonBorder.getBounds(); 
				if(tx > rect.left && tx < rect.right && ty > rect.top && ty < rect.bottom) {
					takeTurn(Selected, SelectedVertical, CurrentPlayer);
					++CurrentPlayer;
					if(CurrentPlayer > GameRecord.PlayerTwo) {
						CurrentPlayer = GameRecord.PlayerOne;
					}
				}
				
				DrawSelection = false;
				Selected = -1;
			}
			
			invalidate();
			
			return true;
		}
		
		return super.onTouchEvent(event);
	}
}
